import * as THREE from "three";
import * as kokomi from "kokomi.js";
import type Experience from "../Experience";

/**
 * 车身尺寸标注组件
 * 在车身高亮时显示车辆的长、宽、高等尺寸信息
 */
export default class CarDimensions extends kokomi.Component {
  declare base: Experience;
  dimensionGroup: THREE.Group;
  isVisible: boolean = false;

  constructor(base: Experience) {
    super(base);

    this.dimensionGroup = new THREE.Group();
    this.dimensionGroup.visible = false;
    this.createDimensionLines();
    
    // 设置标注组的旋转角度，使其与车身视角一致
    this.dimensionGroup.rotation.y = -Math.PI * 0.25; // 约-27度角
  }

  /**
   * 创建尺寸标注线
   */
  createDimensionLines() {
    // 创建材质
    const lineMaterial = new THREE.LineBasicMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.6,
    });

    // 长度标注 (底部前后) - 4997mm
    this.createDimensionLine(
      new THREE.Vector3(-3.0, 0.1, -1.7),
      new THREE.Vector3(2.0, 0.1,-1.7),
      "4997mm",
      lineMaterial
    );

    // 轴距标注 (底部中间) - 3000mm
    this.createDimensionLine(
      new THREE.Vector3(-1.0, 0.05, -1.2),
      new THREE.Vector3(1.0, 0.05, -1.2),
      "3000mm",
      lineMaterial
    );

    // 高度标注 (左侧) - 1440mm
    this.createDimensionLine(
      new THREE.Vector3(3, 0.0, -1.0),
      new THREE.Vector3(3, 1.2, -1.0),
      "1440mm",
      lineMaterial,
      "vertical"
    );

    // 轮距标注 (右前轮) - 1963mm
    this.createDimensionLine(
      // （前后，上下，左右）
      new THREE.Vector3(2.0, 0.1, -1),
      new THREE.Vector3(2.0, 0.1, 1),
      "1963mm",
      lineMaterial,
      "depth"
    );
  }

  /**
   * 创建单个尺寸标注
   */
  createDimensionLine(
    start: THREE.Vector3,
    end: THREE.Vector3,
    label: string,
    material: THREE.LineBasicMaterial,
    orientation: "horizontal" | "vertical" | "depth" = "horizontal"
  ) {
    const group = new THREE.Group();

    // 创建虚线
    const points = [];
    const segments = 20;
    for (let i = 0; i <= segments; i++) {
      const t = i / segments;
      const point = new THREE.Vector3().lerpVectors(start, end, t);
      points.push(point);
    }

    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    
    // 使用LineDashedMaterial创建虚线效果
    const dashedMaterial = new THREE.LineDashedMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.6,
      dashSize: 0.1,
      gapSize: 0.05,
    });
    const dashedLine = new THREE.Line(geometry, dashedMaterial);
    dashedLine.computeLineDistances();
    group.add(dashedLine);

    // 创建端点标记
    const markerGeometry = new THREE.SphereGeometry(0.02, 8, 8);
    const markerMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
    
    const startMarker = new THREE.Mesh(markerGeometry, markerMaterial);
    startMarker.position.copy(start);
    group.add(startMarker);

    const endMarker = new THREE.Mesh(markerGeometry, markerMaterial);
    endMarker.position.copy(end);
    group.add(endMarker);

    // 创建箭头指示
    this.createArrow(group, start, end, material);

    // 创建文字标签 (使用HTML元素)
    const midPoint = new THREE.Vector3().lerpVectors(start, end, 0.5);
    this.createTextLabel(midPoint, label, orientation);

    this.dimensionGroup.add(group);
  }

  /**
   * 创建箭头
   */
  createArrow(
    group: THREE.Group,
    start: THREE.Vector3,
    end: THREE.Vector3,
    material: THREE.LineBasicMaterial
  ) {
    const arrowSize = 0.08;
    const direction = new THREE.Vector3().subVectors(end, start).normalize();
    const perpendicular = new THREE.Vector3(-direction.y, direction.x, 0).normalize();

    // 起点箭头
    const startArrow1 = [
      start.clone(),
      start.clone().add(direction.clone().multiplyScalar(arrowSize))
        .add(perpendicular.clone().multiplyScalar(arrowSize * 0.5))
    ];
    const startArrow2 = [
      start.clone(),
      start.clone().add(direction.clone().multiplyScalar(arrowSize))
        .sub(perpendicular.clone().multiplyScalar(arrowSize * 0.5))
    ];

    // 终点箭头
    const endArrow1 = [
      end.clone(),
      end.clone().sub(direction.clone().multiplyScalar(arrowSize))
        .add(perpendicular.clone().multiplyScalar(arrowSize * 0.5))
    ];
    const endArrow2 = [
      end.clone(),
      end.clone().sub(direction.clone().multiplyScalar(arrowSize))
        .sub(perpendicular.clone().multiplyScalar(arrowSize * 0.5))
    ];

    [startArrow1, startArrow2, endArrow1, endArrow2].forEach(points => {
      const geo = new THREE.BufferGeometry().setFromPoints(points);
      const line = new THREE.Line(geo, material);
      group.add(line);
    });
  }

  /**
   * 创建文字标签 (CSS2D)
   */
  createTextLabel(position: THREE.Vector3, text: string, _orientation: string) {
    const div = document.createElement("div");
    div.className = "dimension-label";
    div.textContent = text;
    div.style.cssText = `
      position: absolute;
      color: white;
      font-size: 12px;
      font-family: Arial, sans-serif;
      background: rgba(0, 0, 0, 0.5);
      padding: 2px 6px;
      border-radius: 3px;
      pointer-events: none;
      white-space: nowrap;
      transform: translate(-50%, -50%);
    `;

    document.body.appendChild(div);

    // 存储标签以便更新位置
    const labelData = { div, position: position.clone() };
    if (!(this.dimensionGroup as any).labels) {
      (this.dimensionGroup as any).labels = [];
    }
    (this.dimensionGroup as any).labels.push(labelData);
  }

  /**
   * 添加到场景
   */
  addExisting() {
    this.container.add(this.dimensionGroup);
  }

  /**
   * 显示尺寸标注
   */
  show() {
    this.isVisible = true;
    this.dimensionGroup.visible = true;
    
    // 显示所有标签
    if ((this.dimensionGroup as any).labels) {
      (this.dimensionGroup as any).labels.forEach((labelData: any) => {
        labelData.div.style.display = "block";
      });
    }
  }

  /**
   * 隐藏尺寸标注
   */
  hide() {
    this.isVisible = false;
    this.dimensionGroup.visible = false;
    
    // 隐藏所有标签
    if ((this.dimensionGroup as any).labels) {
      (this.dimensionGroup as any).labels.forEach((labelData: any) => {
        labelData.div.style.display = "none";
      });
    }
  }

  /**
   * 每帧更新 - 更新标签位置
   */
  update() {
    if (!this.isVisible) return;

    const camera = this.base.camera;
    const canvas = this.base.renderer.domElement;
    const rect = canvas.getBoundingClientRect();

    if ((this.dimensionGroup as any).labels) {
      (this.dimensionGroup as any).labels.forEach((labelData: any) => {
        const position = labelData.position.clone();
        position.project(camera);

        const x = (position.x * 0.5 + 0.5) * rect.width + rect.left;
        const y = (-position.y * 0.5 + 0.5) * rect.height + rect.top;

        labelData.div.style.left = `${x}px`;
        labelData.div.style.top = `${y}px`;
      });
    }
  }

  /**
   * 销毁组件
   */
  destroy() {
    if ((this.dimensionGroup as any).labels) {
      (this.dimensionGroup as any).labels.forEach((labelData: any) => {
        labelData.div.remove();
      });
    }
    this.dimensionGroup.clear();
  }
}
